package com.msh.frame.client.base;

import com.msh.frame.client.common.ErrorCode;
import com.msh.frame.client.common.Result;
import com.msh.frame.client.exception.BizException;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.util.CollectionUtils;

/**
 * @author shihu 基本serivce方法实现
 */
public abstract class BaseServiceImpl<T extends BasePo, Q extends BaseQo> implements
    BaseService<T, Q> {

  private BaseDao baseDao;

  @Override
  public long insert(T param) {
    long result = getBaseDao().insert(param);
    BizException.doThrowIfTrue(ErrorCode.DB_INSERT_EMPTY, result == 0);
    return param.getId();
  }

  @Override
  public int insertCollection(Collection<T> param) {
    return getBaseDao().insertCollection(param);
  }

  @Override
  public void update(T param) {
    long result = getBaseDao().update(param);
    BizException.doThrowIfTrue(ErrorCode.PARAM_NOT_MATCHING, result == 0);
  }

  @Override
  public T get(Long id) {
    return getBaseDao().get(id);
  }

  @Override
  public List<T> getByIds(Collection<Long> ids) {
    return getBaseDao().getByIds(ids);
  }

  @Override
  public int count(Q param) {
    return getBaseDao().count(param);
  }

  @Override
  public List<T> list(Q param) {
    return getBaseDao().list(param);
  }

  @Override
  public Result<List<T>> page(Q param) {
    int count = count(param);
    List<T> result;
    if (0 == count) {
      result = Collections.emptyList();
    } else {
      result = list(param);
    }
    return Result.successReturn(result).setCount(count);
  }

  @Override
  public T listOne(Q param) {
    param.setPageSize(1);
    List<T> result = getBaseDao().list(param);
    if (!CollectionUtils.isEmpty(result)) {
      return result.get(0);
    }
    return null;
  }

  @Override
  public int delete(Long id) {
    return getBaseDao().delete(id);
  }

  @Override
  public int deleteByIds(Collection<Long> ids) {
    return getBaseDao().deleteByIds(ids);
  }

  @Override
  public int deleteByQo(Q q) {
    q.setColumns("id");
    Set<Long> idSet = list(q).stream().map(T::getId).collect(Collectors.toSet());
    if(CollectionUtils.isEmpty(idSet)){
      return 0;
    }
    return deleteByIds(idSet);
  }

  @Override
  public Map<Long, T> map(Q q) {
    return this.list(q).stream()
        .collect(Collectors.toMap(T::getId, c -> c));
  }

  @Override
  public Map<Long, T> map(Collection<Long> ids) {
    if (CollectionUtils.isEmpty(ids)) {
      return Collections.emptyMap();
    }
    return this.getByIds(ids).stream()
        .collect(Collectors.toMap(T::getId, c -> c));
  }

  public BaseDao<T, Q> getBaseDao() {
    if (null == baseDao) {
      try {
        String filedName = this.getClass().getSimpleName().replace("ServiceImpl", "Dao");
        filedName = (new StringBuilder()).append(Character.toLowerCase(filedName.charAt(0)))
            .append(filedName.substring(1)).toString();
        Field field = this.getClass().getDeclaredField(filedName);
        field.setAccessible(true);
        baseDao = (BaseDao<T, Q>) field.get(this);
        field.setAccessible(false);
      } catch (NoSuchFieldException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
    }
    return baseDao;
  }
}
